home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * lister event.c -- Version 3.0
- *
- * Developer Technical Support Apple II Sample Code
- *
- * Copyright (c)
- * Apple Computer, Inc. 1988-1990
- * All Rights Reserved.
- *
- * Written by Eric Soldan.
- *
- * This file contains the code which implements the
- * main event loop used by the lister program.
- *
- **********************************************************************/
-
- #include <types.h>
- #include <event.h>
- #include <font.h>
- #include <intmath.h>
- #include <lineedit.h>
- #include <locator.h>
- #include <menu.h>
- #include <resources.h>
- #include <window.h>
-
- #include "lister.h"
-
- void doChangeTabs();
- void getTabsInfo();
- void i2pstr();
- void mainWindowDraw();
-
- /**********************************************************************
- *
- * mainEvent
- *
- * This is the main part of the program. The program cycles in this
- * loop until the user chooses quit.
- *
- **********************************************************************/
-
- void mainEvent()
- {
- WindowPtr wptr, keepPort;
- unsigned long id;
- unsigned int item, rad, i, part, val;
- FontID newFont;
- CtlRecHndl ctlHndl;
-
- zapLocals();
-
- keepPort = GetPort();
-
- wptr = NewWindow2(NULL, NULL, NULL, NULL, 2, MainWindowID, rWindParam1);
- if (!_toolErr) {
-
- mainWindow = wptr;
-
- /* This gets kind of weird here. The MainWindow also includes
- ** some of the TabsWindow controls. This is so that the data
- ** in the resources is loaded in. The info is then extracted,
- ** and then the controls are disposed of. Once all of this is
- ** done, the window is made visible. This is actually the
- ** easiest way to initially get the data from the TabsWindow
- ** control resources. */
-
- getTabsInfo(); /* Extract tabs data and put in print structure. */
-
- for (i = (unsigned int)TabsData; i < (unsigned int)(TabChr + 1); i++)
- DisposeControl(GetCtlHandleFromID(wptr, (long)i));
- /* Dispose the TabsWindow controls. */
-
- MakeThisCtlTarget(GetCtlHandleFromID(mainWindow, Header));
- /* Depending on the order of the controls, we may have just deleted
- ** the target control. Make sure we have a target. */
-
-
- ShowWindow(wptr); /* Now that everything is okay, show window. */
- SelectWindow(wptr);
-
- for (;;) {
- id = fakeModalDialog(&event, mainWindowDraw, handleKeys, NULL,
- fmdMenuSelect+
- fmdMenuKey+
- fmdIBeam+
- fmdDeskAcc+
- fmdUpdateAll+
- fmdMovable
- );
- item = id;
- if (id & 0x80000000L) { /* Hi-bit on? It's a menu command. */
- doMenuCommand(id);
- if (quitFlag) break; /* It was a quit menu command. */
- }
- else {
- switch (item) { /* User clicked on ctl -- handle it. */
- case ChFont:
- newFont.fidLong = ChooseFont(print.theFont.fidLong, 0);
- if (newFont.fidLong) { /* Check for cancel. */
- if (newFont.fidRec.fontSize > 42)
- newFont.fidRec.fontSize = 42;
- print.theFont.fidLong = newFont.fidLong;
- }
- break;
- case ChangeTabs:
- doChangeTabs();
- break;
- case BoxProc:
- part = fmdGetCtlPart();
- ctlHndl = GetCtlHandleFromID(mainWindow, BoxProc);
- val = GetCtlValue(ctlHndl);
- val ^= (1 << --part);
- SetCtlValue(val, ctlHndl);
- break;
- }
- if (quitFlag) break;
- /* User chose quit while tabs window was up. */
- }
- }
-
- SetPort(keepPort);
- CloseWindow(wptr);
- mainWindow = NULL;
- }
- }
-
- /**********************************************************************/
-
- pascal void handleKeys(event)
- WmTaskRec* event;
- {
- WindowPtr wptr;
- unsigned int c, e, i, j, m, digitsOnly, myWind;
- CtlRecHndl ctlHndl;
- LERecPtr lePtr;
-
- static char validChrs[] = {
- 6, /* Allow char-right-of-cursor delete. */
- 8, /* Allow left arrow. */
- 9, /* Allow tab key. */
- 13, /* Allow default button. */
- 21, /* Allow right arrow. */
- 24, /* Allow ctrl-x to clear field. */
- 25, /* Allow delete to end-of-line. */
- 127, /* Allow delete. */
- 0 /* End of list. */
- }; /* These are the valid lineEdit editing keys. Allow them. */
-
- zapLocals();
-
- /* (*ctlHndl)->ctlData = NULL; */
-
- /* The above commented-out code is a test of the uninitialized
- ** pointer testing. If productionVersion is set to 0, then
- ** uninitialized pointer testing is done in this application.
- ** If the above commented code is uncommented, then we have just
- ** created an instance where an uninitialized pointer (or handle
- ** in this case) is used. It doesn't matter how many levels of
- ** dereferencing is done. The local checker will still find the
- ** problem. If you uncomment the code above, make sure that you
- ** don't compile this program with the productionVersion switch
- ** true. If you do this, you will be using an uninitialized
- ** pointer without checking for it. You will actually be
- ** clobbering memory, and who knows how you will crash, or when.
- ** Also note that you can set the ctlHndl to NULL before using
- ** it. The pointer checking code will catch this also.
- ** It will not, hwever catch a usage of a NULL pointer. Using
- ** a NULL pointer will not index into the test bank of RAM,
- ** and is therefore undetectable.
- */
-
- if ( ((e = event->what) == keyDownEvt) || (e == autoKeyEvt) ) {
- /* Only filter/modify key events. */
-
- wptr = FrontWindow(); /* Filtering varies, depends on window. */
- digitsOnly = myWind = 0; /* Initialize some flags. */
-
- if (wptr == mainWindow) { /* See if front window is app. window. */
- myWind++; /* It is. */
- if (GetCtlID(FindTargetCtl()) == Columns)
- digitsOnly++; /* Only digits for Columns editLine ctl. */
- }
-
- if (wptr == tabsWindow) { /* See if front window is app. window. */
- myWind++; /* It is. */
- digitsOnly++; /* It is the tabs window. */
- if (GetCtlID(ctlHndl = FindTargetCtl()) == TabsData)
- digitsOnly++; /* Allow commas and the ellipses char. */
- } /* also for this editLine item. */
-
- if (!myWind) return; /* It is a DA, so allow everything. */
-
- c = event->message & 0xFF;
- m = event->modifiers & (appleKey | shiftKey | optionKey | controlKey);
-
- if (!(m & appleKey)) { /* If appleKey mod was not held down. */
-
- for (i = 0; j = validChrs[i]; i++) if (c == j) return;
- /* If it is a valid editLine editing character, allow it. */
-
- if (c == 27) { /* Convert ESC event to OA-. event. */
- *(char *)&(event->message) = '.';
- event->modifiers |= appleKey;
- return;
- } /* This conversion of an ESC to an OA-. allows us to
- ** be able to have two key equivalents with different
- ** modifiers. Dirrefing modifiers isn't supported by
- ** the toolbox, so we have to fake it. Given that we
- ** can convert any event to any other event before
- ** fakeModalDialog processes it, we can have as many
- ** key equivalents for a control as we want. We are
- ** no longer limited to two with the same modifiers.
- */
-
- if (digitsOnly == 2) { /* If tabsData editLine... */
- if (c == ',') return; /* Commas are okay. */
- if (c == 0xC9) { /* Ellipses char is ok at end. */
- lePtr = *(LERecHndl)(*ctlHndl)->ctlData;
- if (lePtr->leSelEnd < lePtr->leLength)
- event->what = 0; /* We weren't at end of line. */
- return;
- }
- } /* I realize that there are some cases missing here.
- ** I didn't feel like dealing with them. Like, hey
- ** man, this is sample code for programmers -- cut me
- ** some slack. One case that isn't handled is that you
- ** can type other characters after an ellipses.
- ** Therefore, the ellipses character may not end up as
- ** the end character. I can live with this, since the
- ** tabbing code handles a comma and an ellipses
- ** character exactly the same anyway. The ellipses
- ** is supported for user-readability. If the user
- ** wants to put them in funny places, then fine.
- */
-
- if (digitsOnly) if ((c < '0') || (c > '9')) event->what = 0;
- /* If we are allowing only digits, then kill others. */
-
- if (c < 32) event->what = 0;
- /* Kill all control characters not previously allowed. */
-
- return;
- }
- }
- }
-
- /**********************************************************************/
-
- void doChangeTabs()
- {
- WindowPtr wptr, keepPort;
- unsigned long id;
- unsigned int item;
- char str[42];
-
- zapLocals();
-
- keepPort = GetPort();
-
- wptr = NewWindow2(NULL, NULL, NULL, NULL, 2, TabsWindowID, rWindParam1);
- if (!_toolErr) {
- tabsWindow = wptr;
-
- fmdLESetText(wptr, TabsData, print.tabsData);
- i2pstr(str, print.tabChr);
- fmdLESetText(wptr, TabChr, str);
- /* Since this might not be the first time this window is opened,
- ** fill the LineEdit controls with the text from last time,
- ** instead of using the data from the resources.
- */
-
- for (;;) {
- id = fakeModalDialog(&event, NULL, handleKeys, NULL,
- fmdMenuSelect+
- fmdMenuKey+
- fmdIBeam+
- fmdDeskAcc+
- fmdUpdateAll+
- fmdMovable
- );
- item = id; /* Get lo-word. */
- if (id & 0x80000000L) { /* If menu command... */
- if (item == 255) {
- HiliteMenu(0, FileMenuID); /* Nobody else will. */
- break; /* If close, then close */
- } /* the tabs window. */
- doMenuCommand(id);
- if (quitFlag) break;
- }
- else {
- if (item == 1) { /* ...else handle controls. */
- getTabsInfo(); /* Extract the data before */
- break; /* before closing window. */
- }
- if (item == 2) break; /* User cancelled. */
- if (
- (item >= (unsigned int)MerlinTabs) &&
- (item < (unsigned int)TabsData)
- ) {
- fmdLEGetText(wptr, (unsigned long)(item + 1), str);
- fmdLESetText(wptr, TabsData, str);
- } /* User pressed the Merlin button, or some other
- ** button that was added to the resource fork.
- ** When one of these buttons is pressed, take
- ** the data from the inactive, invisible, and way
- ** the heck outside the window lineEdit control
- ** and put it into the tabsData control. Given
- ** the fakeModalDialog data access routines, this
- ** method of hiding the data in a lineEdit
- ** control is actually the easiest.
- */
- }
- }
-
- SetPort(keepPort);
- CloseWindow(wptr);
- tabsWindow = NULL;
- appSetMenus(); /* This is necessary because the window just
- ** behind the one we are closing could be a DA.
- ** DA's get the activate events, and therefore
- ** fakeModalDialog doesn't get to see the
- ** activate event, and therefore doesn't get a
- ** chance to update the menus to reflect the new
- ** front window. Due to this, we do a direct
- ** call to the menu update routine ourselves.
- ** This should be done whenever we are closing a
- ** window. Closing a window is the only
- ** circumstance where fakeModalDialog may not
- ** automatically call the menu update routine,
- ** so we do it ourselves as a good practice.
- */
- }
- }
-
- /**********************************************************************/
-
- void getTabsInfo()
- {
- WindowPtr wptr;
- unsigned int i;
-
- zapLocals();
-
- wptr = mainWindow;
- if (tabsWindow) wptr = tabsWindow;
-
- /* If we have a tabsWindow, then we want to get the data
- ** from that window. If we don't, then we are being
- ** called for the first time. When the main window is
- ** initially opened, it has the lineEdit controls from
- ** the tabs window as well. This is so that we can
- ** initially get the data for the tabs window. We need
- ** to get the data at this point because the user may
- ** not ever choose to open the tabs window. Once the
- ** main window is opened and the data is extracted, the
- ** tabs window controls will be disposed.
- */
-
- fmdLEGetText(wptr, TabChr, print.tabsData);
- /* Use print.tabsData as a workspace. */
-
- if (!fmdGetError()) {
- i = atoi(print.tabsData + 1) & 0xFF;
- if (!i) i = 9;
- if (i > 255) i = 9;
- print.tabChr = i;
- }
-
- fmdLEGetText(wptr, TabsData, print.tabsData);
- /* Now use print.tabsData for real. */
- }
-
- /**********************************************************************/
-
- void mainWindowDraw()
- {
- fmdStdDrawProc();
-
- /* This routine is here as an example, even though we don't need it.
- ** If you pass a NULL to fakeModalDialog as the updateProc, then
- ** fakeModalDialog uses fmdStdDrawProc. You can override this by
- ** supplying your own. If you supply your own, you can still have
- ** fakeModalDialog do the standard stuff, simply by calling
- ** fmdStdDrawProc yourself. If we then had any additional stuff to
- ** do, we could then do it here as well. In this example, since we
- ** aren't doing anything beyond calling fmdStdDrawProc, we could
- ** have simply passed fakeModalDialog a NULL.
- */
- }
-